﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.IO;

namespace CompareCopy
{
    public partial class MainForm : Form
    {
        /// <summary>
        /// 配置文件路径
        /// </summary>
        private string configPath = Application.StartupPath + "\\config.xml";
        private DataTable copyTable = new DataTable();
        private Dictionary<string, string> sourceDic = new Dictionary<string, string>();//比较过的

        public MainForm()
        {
            InitializeComponent();
            copyTable.Columns.Add("Source");
            copyTable.Columns.Add("Dest");
        }

        private void button_Brows_Click(object sender, EventArgs e)
        {
            if(folderBrowserDialog1.ShowDialog() == DialogResult.OK)
            {
                textBox_MainFolder.Text = folderBrowserDialog1.SelectedPath;
            }
        }

        private void button_Add_Click(object sender, EventArgs e)
        {
            if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
            {
                listBox_target.Items.Add(folderBrowserDialog1.SelectedPath);

            }
        }

        private void button_Del_Click(object sender, EventArgs e)
        {
            while(listBox_target.SelectedItems.Count > 0)
            {
                listBox_target.Items.Remove(listBox_target.SelectedItems[0]);
            }
        }

        string sourceFolder = "";
        List<string> targetFolders = new List<string>();
        string fileFilter = "";
        List<string> extFilter = new List<string>();
        private void button_Compare_Click(object sender, EventArgs e)
        {
            button_Compare.Enabled = false;
            if(String.IsNullOrEmpty(textBox_MainFolder.Text))
            {
                MessageBox.Show("Please select main folder!");
                return;
            }
            if (!Directory.Exists(textBox_MainFolder.Text))
            {
                MessageBox.Show("Main folder not exist!");
                return;
            }
            if (listBox_target.Items.Count == 0)
            {
                MessageBox.Show("Please select target folders!");
                return;
            }
            extFilter.Clear();
            if (textBox_MainFolder.Text.Last() != '\\')
                sourceFolder = textBox_MainFolder.Text + "\\";
            targetFolders.Clear();
            toolStripProgressBar1.Value = 0;
            foreach (string str in listBox_target.Items)
            {
                if (str.Last() != '\\')
                    targetFolders.Add(str + "\\");
                else
                    targetFolders.Add(str);

            }
            fileFilter = comboBox_Filter.Text.Replace('；',';');
            string[] filters = fileFilter.Replace("*", "").Split(';');
            foreach(string f in filters)
            {
                extFilter.Add(f);
            }
            listView1.Items.Clear();
            backgroundWorker1.RunWorkerAsync();

            toolStripStatusLabel1.Text = "开始搜索原始目录";
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            DirectoryInfo dirInfo = new DirectoryInfo(sourceFolder);
            CompareFile(dirInfo);
        }

        private void CompareFile(DirectoryInfo dirInfo)
        {
            sourceDic.Clear();
            FileInfo[] fiList = dirInfo.GetFiles("*.*", SearchOption.AllDirectories);
            for (int n = 0; n < fiList.Length; n++  )
            {
                FileInfo fi = fiList[n];
                if (extFilter.Contains(Path.GetExtension(fi.FullName)))
                {
                    for (int i = 0; i < targetFolders.Count; i++)
                    {
                        //正向比较
                        string targetFile = targetFolders[i] + fi.FullName.Substring(sourceFolder.Length);
                        backgroundWorker1.ReportProgress((int)(n * 100.0 / fiList.Length), targetFile);
                        //只比较没有比较过的
                        if (!sourceDic.ContainsKey(targetFile))
                        {
                            sourceDic.Add(targetFile, targetFile.Substring(targetFolders[i].Length));
                            if (File.Exists(targetFile))
                            {
                                string sourceMD5 = MD5Helper.GetMD5HashFromFile(fi.FullName);
                                string targetMD5 = MD5Helper.GetMD5HashFromFile(targetFile);

                                if (sourceMD5 != targetMD5)
                                {
                                    ListViewItem lv = new ListViewItem(fi.FullName);
                                    lv.SubItems.Add(targetFile);
                                    lv.SubItems.Add(fi.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss"));
                                    FileInfo targetInfo = new FileInfo(targetFile);
                                    lv.SubItems.Add(targetInfo.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss"));
                                    lv.SubItems.Add(Tools.HumanReadableFilesize(fi.Length));
                                    lv.SubItems.Add(Tools.HumanReadableFilesize(targetInfo.Length));

                                    safeAddItem(lv);
                                }
                            }
                            else
                            {//目标文件不存在
                                ListViewItem lv = new ListViewItem(fi.FullName);
                                lv.SubItems.Add(targetFile);
                                lv.SubItems.Add(fi.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss"));

                                lv.SubItems.Add("不存在");
                                lv.SubItems.Add(Tools.HumanReadableFilesize(fi.Length));
                                lv.SubItems.Add("0B");

                                safeAddItem(lv);
                            }
                        }
                        //反向比较
                        DirectoryInfo targetFolder = new DirectoryInfo(targetFolders[i]);
                        FileInfo[] targetfiList = targetFolder.GetFiles("*.*", SearchOption.AllDirectories);
                        for (int j = 0; j < targetfiList.Length; j++)
                        {
                            FileInfo targetFileInfo = targetfiList[j];
                            if (extFilter.Contains(Path.GetExtension(targetFileInfo.FullName)))
                            {
                                //只比较还没有比较过的
                                if(!sourceDic.ContainsKey(targetFileInfo.FullName))
                                {
                                    string sourceFile = sourceFolder + targetFileInfo.FullName.Substring(targetFolders[i].Length);
                                    sourceDic.Add(targetFileInfo.FullName, targetFileInfo.FullName.Substring(targetFolders[i].Length));

                                    if (File.Exists(sourceFile))
                                    {
                                        string sourceMD5 = MD5Helper.GetMD5HashFromFile(sourceFile);
                                        string targetMD5 = MD5Helper.GetMD5HashFromFile(targetFileInfo.FullName);

                                        if (sourceMD5 != targetMD5)
                                        {
                                            FileInfo sourceInfo = new FileInfo(sourceFile);
                                            ListViewItem lv = new ListViewItem(sourceFile);
                                            lv.SubItems.Add(targetFileInfo.FullName);
                                            lv.SubItems.Add(sourceInfo.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss"));
                                            
                                            lv.SubItems.Add(targetFileInfo.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss"));
                                            lv.SubItems.Add(Tools.HumanReadableFilesize(sourceInfo.Length));
                                            lv.SubItems.Add(Tools.HumanReadableFilesize(targetFileInfo.Length));

                                            safeAddItem(lv);
                                        }
                                    }
                                    else
                                    {//原始文件不存在
                                        FileInfo sourceInfo = new FileInfo(sourceFile);
                                        ListViewItem lv = new ListViewItem(sourceFile);
                                        lv.SubItems.Add(targetFileInfo.FullName);
                                        lv.SubItems.Add("已删除");

                                        lv.SubItems.Add(targetFileInfo.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss"));
                                        lv.SubItems.Add("0B");
                                        lv.SubItems.Add(Tools.HumanReadableFilesize(targetFileInfo.Length));

                                        safeAddItem(lv);
                                    }
                                }
                            }
                        }
                    }
                }
               
            }
            //DirectoryInfo[] dirs = dirInfo.GetDirectories();
            //foreach (DirectoryInfo di in dirs)
            //{
            //    CompareFile(di);
            //}
       }
        //安全添加列表数据的委托
        private delegate void _SafeAddItemCall(ListViewItem tlv);
        private void safeAddItem(ListViewItem tlv)
        {
            if (this.listView1.InvokeRequired)
            {
                _SafeAddItemCall call = delegate (ListViewItem s)
                {
                    listView1.Items.Add(s);
                };

                listView1.Invoke(call, tlv);
            }
            else
                listView1.Items.Add(tlv);
        }
        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            toolStripProgressBar1.Value = e.ProgressPercentage;
            toolStripStatusLabel1.Text = e.UserState.ToString();
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            toolStripStatusLabel1.Text = "Compare Completed!";
            toolStripProgressBar1.Value = 100;
            button_Compare.Enabled = true;
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            if (File.Exists(configPath))
            {
                ConfigData configData = Config.XMLDeserialize(configPath);
                textBox_MainFolder.Text = configData.SourceFolder;
                foreach (string s in configData.TargetFolder)
                {
                    listBox_target.Items.Add(s);
                }
                comboBox_Filter.Text = configData.FileFilter;
            }
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            ConfigData configData = new ConfigData();
            configData.SourceFolder = textBox_MainFolder.Text;
            configData.FileFilter = comboBox_Filter.Text;
            foreach (string s in listBox_target.Items)
            {
                configData.TargetFolder.Add(s);
            }

            Config.XMLSerialize(configData, configPath);
        }

        private void copyWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            for(int i = 0; i < copyTable.Rows.Count;i++)
            {
                try
                {
                    string source = copyTable.Rows[i]["Source"].ToString();
                    string dest = copyTable.Rows[i]["Dest"].ToString();

                    if(!File.Exists(source))
                    {
                        //原始左侧不存在
                        File.Delete(dest);
                    }
                    else
                    {
                        if (!Directory.Exists(Path.GetDirectoryName(dest)))
                            Directory.CreateDirectory(Path.GetDirectoryName(dest));
                        File.Copy(source, dest, true);
                    }

                    copyWorker.ReportProgress((int)(i * 100.0 / copyTable.Rows.Count), dest);
                }
                catch(Exception ex)
                {
                    MessageBox.Show(ex.Message, "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
            }
        }

        private void copyWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            toolStripProgressBar1.Value = e.ProgressPercentage;
            toolStripStatusLabel1.Text = "Write:" + e.UserState.ToString();
        }

        private void copyWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            toolStripStatusLabel1.Text = "Copy Completed!";
            toolStripProgressBar1.Value = 100;
            button_Copy.Enabled = true;
        }


        private void button_Copy_Click(object sender, EventArgs e)
        {
            button_Copy.Enabled = false;
            copyTable.Rows.Clear();
            toolStripProgressBar1.Value = 0;
            for (int i = 0; i <  listView1.Items.Count;i++)
            {
                copyTable.Rows.Add(
                    listView1.Items[i].SubItems[0].Text,
                    listView1.Items[i].SubItems[1].Text);
            }

            copyWorker.RunWorkerAsync();
        }
    }
}
